package liquibase.database.core;

import liquibase.CatalogAndSchema;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.DatabaseConnection;
import liquibase.database.OfflineConnection;
import liquibase.exception.DatabaseException;
import liquibase.exception.ValidationErrors;
import liquibase.executor.ExecutorService;
import liquibase.logging.LogService;
import liquibase.logging.LogType;
import liquibase.statement.core.RawCallStatement;
import liquibase.structure.core.Schema;
import liquibase.util.StringUtils;

import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

public class DMDatabase extends AbstractJdbcDatabase {
    private static final String PRODUCT_NAME = "dm";
    private Set<String> reservedWords = new HashSet();

    public DMDatabase() {
        super.unquotedObjectsAreUppercased = true;
        super.setCurrentDateTimeFunction("NOW()");
    }

    public String getShortName() {
        return "dm";
    }

    protected String getDefaultDatabaseProductName() {
        return "DM";
    }

    public Integer getDefaultPort() {
        return 5236;
    }

    public String getDefaultDriver(String url) {
        return url.startsWith("jdbc:dm") ? "dm.jdbc.driver.DmDriver" : null;
    }

    public boolean isReservedWord(String objectName) {
        return this.reservedWords.contains(objectName.toUpperCase());
    }

    protected String getConnectionCatalogName() throws DatabaseException {
        if (this.getConnection() instanceof OfflineConnection) {
            return this.getConnection().getCatalog();
        } else {
            try {
                return ExecutorService.getInstance().getExecutor(this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);
            } catch (Exception var2) {
                LogService.getLog(this.getClass()).info(LogType.LOG, "Error getting default schema", var2);
                return null;
            }
        }
    }

    public String getDateLiteral(String isoDate) {
        String normalLiteral = super.getDateLiteral(isoDate);
        StringBuffer val;
        if (this.isDateOnly(isoDate)) {
            val = new StringBuffer();
            val.append("TO_DATE(");
            val.append(normalLiteral);
            val.append(", 'YYYY-MM-DD')");
            return val.toString();
        } else if (this.isTimeOnly(isoDate)) {
            val = new StringBuffer();
            val.append("TO_DATE(");
            val.append(normalLiteral);
            val.append(", 'HH24:MI:SS')");
            return val.toString();
        } else if (this.isTimestamp(isoDate)) {
            val = new StringBuffer(26);
            val.append("TO_TIMESTAMP(");
            val.append(normalLiteral);
            val.append(", 'YYYY-MM-DD HH24:MI:SS.FF')");
            return val.toString();
        } else if (this.isDateTime(isoDate)) {
            int seppos = normalLiteral.lastIndexOf(46);
            if (seppos != -1) {
                normalLiteral = normalLiteral.substring(0, seppos) + "'";
            }

            val = new StringBuffer(26);
            val.append("TO_DATE(");
            val.append(normalLiteral);
            val.append(", 'YYYY-MM-DD HH24:MI:SS')");
            return val.toString();
        } else {
            return "UNSUPPORTED:" + isoDate;
        }
    }

    public ValidationErrors validate() {
        ValidationErrors errors = super.validate();
        DatabaseConnection connection = this.getConnection();
        if (connection != null && !(connection instanceof OfflineConnection)) {
            return errors;
        } else {
            LogService.getLog(this.getClass()).info(LogType.LOG, "Cannot validate offline database");
            return errors;
        }
    }

    public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
        return "DM DBMS".equalsIgnoreCase(conn.getDatabaseProductName());
    }

    public String getDefaultCatalogName() {
        return super.getDefaultCatalogName() == null ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);
    }

    public String getJdbcCatalogName(CatalogAndSchema schema) {
        return null;
    }

    public String getJdbcSchemaName(CatalogAndSchema schema) {
        return this.correctObjectName(schema.getCatalogName() == null ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);
    }

    protected String getAutoIncrementClause(String generationType, Boolean defaultOnNull) {
        if (StringUtils.isEmpty(generationType)) {
            return "";
        } else {
            String autoIncrementClause = "GENERATED %s AS IDENTITY";
            String generationStrategy = generationType;
            if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {
                generationStrategy = generationType + " ON NULL";
            }

            return String.format(autoIncrementClause, generationStrategy);
        }
    }

    public boolean supportsAutoIncrement() {
        return true;
    }

    public boolean supportsRestrictForeignKeys() {
        return false;
    }

    public boolean jdbcCallsCatalogsSchemas() {
        return true;
    }

    public boolean supportsNotNullConstraintNames() {
        return true;
    }

    public boolean supportsInitiallyDeferrableColumns() {
        return true;
    }

    public boolean supportsTablespaces() {
        return true;
    }

    public boolean supportsSchemas() {
        return false;
    }

    public boolean supportsSequences() {
        return true;
    }

    public int getPriority() {
        return 1;
    }
}
